home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.002 / stk-3 / STk-3.1 / Lib / text.stk < prev    next >
Encoding:
Text File  |  1996-07-05  |  21.6 KB  |  691 lines

  1. ;;;;
  2. ;;;; Texts bindings and procs (bindings a` la emacs)
  3. ;;;;
  4. ;;;; Copyright ⌐ 1993-1996 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
  5. ;;;; 
  6. ;;;; Permission to use, copy, and/or distribute this software and its
  7. ;;;; documentation for any purpose and without fee is hereby granted, provided
  8. ;;;; that both the above copyright notice and this permission notice appear in
  9. ;;;; all copies and derived works.  Fees for distribution or use of this
  10. ;;;; software or derived works may only be charged with express written
  11. ;;;; permission of the copyright holder.  
  12. ;;;; This software is provided ``as is'' without express or implied warranty.
  13. ;;;;
  14. ;;;; This software is a derivative work of other copyrighted softwares; the
  15. ;;;; copyright notices of these softwares are placed in the file COPYRIGHTS
  16. ;;;;
  17. ;;;;
  18. ;;;;           Author: Erick Gallesio [eg@unice.fr]
  19. ;;;;    Creation date: 17-May-1993 12:35
  20. ;;;; Last file update:  5-Jul-1996 15:48
  21. ;;;;
  22.  
  23.  
  24. ;; Tk:text-clipboard-keysyms
  25. ;; This procedure is invoked to identify the keys that correspond to
  26. ;; the "copy", "cut", and "paste" functions for the clipboard.
  27. ;;
  28. ;; Arguments:
  29. ;; copy -    Name of the key (keysym name plus modifiers, if any,
  30. ;;        such as "Meta-y") used for the copy operation.
  31. ;; cut -        Name of the key used for the cut operation.
  32. ;; paste -    Name of the key used for the paste operation.
  33.  
  34. (define (Tk:text-clipboard-keysyms copy cut paste)
  35.   (define-binding "Text" copy (|W|)
  36.     (when (equal? [selection 'own :displayof |W|] |W|)
  37.        (clipboard 'clear :displayof |W|)
  38.        (catch 
  39.       (clipboard 'append :displayof |W| (selection 'get :displayof |W|)))))
  40.  
  41.   (define-binding "Text" cut (|W|)
  42.     (when (equal? [selection 'own :displayof |W|] (widget->string |W|))
  43.        (clipboard 'clear :displayof |W|)
  44.        (catch
  45.       (clipboard 'append :displayof |W| (selection 'get :displayof |W|))
  46.       (|W| 'delete 'sel.first 'sel.last))))
  47.  
  48.   (define-binding "Text" paste (|W|)
  49.     (catch
  50.        (|W| 'insert 'insert (selection 'get :displayof |W| 
  51.                             :selection "CLIPBOARD"))))
  52. )
  53.  
  54.  
  55. ;; Tk:text-button-1 --
  56. ;; This procedure is invoked to handle button-1 presses in "Text"
  57. ;; widgets.  It moves the insertion cursor, sets the selection anchor,
  58. ;; and claims the input focus.
  59. ;;
  60. ;; w -        The "Text" windselectow in which the button was pressed.
  61. ;; x -        The x-coordinate of the button press.
  62. ;; y -        The x-coordinate of the button press.
  63.  
  64. (define (Tk:text-button-1 w x y)
  65.   (set! tk::select-mode "char")
  66.   (set! tk::mouse-moved #f)
  67.   (set! tk::press-x x)
  68.   (set! tk::press-y y)
  69.   (w 'mark 'set 'insert (Tk:text-closest-gap w x y))
  70.   (w 'mark 'set 'anchor "insert")
  71.   (if (equal? (tk-get w :state) "normal")
  72.       (focus w)))
  73.  
  74. ;; Tk:text-select-to --
  75. ;; This procedure is invoked to extend the selection, typically when
  76. ;; dragging it with the mouse.  Depending on the selection mode (character,
  77. ;; word, line) it selects in different-sized units.  This procedure
  78. ;; ignores mouse motions initially until the mouse has moved from
  79. ;; one character to another or until there have been multiple clicks.
  80. ;;
  81. ;; w -        The text window in which the button was pressed.
  82. ;; x -        Mouse x position.
  83. ;; y -         Mouse y position.
  84.  
  85. (define (Tk:text-select-to w x y)
  86.   (let ((cur    (Tk:text-closest-gap w x y))
  87.     (first  #f)
  88.     (last   #f)
  89.     (anchor #f))
  90.  
  91.     (if (catch (w 'index 'anchor))
  92.     (w 'mark 'set 'anchor cur))
  93.     (set! anchor (w 'index 'anchor))
  94.  
  95.     (if (or (w 'compare cur "!=" anchor)
  96.         (>= (abs (- tk::press-x x)) 3))
  97.     (set! tk::mouse-moved #t))
  98.  
  99.     (cond
  100.       ((string=? tk::select-mode "char")
  101.                (if (w 'compare cur "<" "anchor")
  102.            (begin
  103.              (set! first cur)
  104.              (set! last "anchor"))
  105.            (begin
  106.              (set! first "anchor")
  107.              (set! last cur))))
  108.       ((string=? tk::select-mode "word")
  109.                 (if (w 'compare cur "<" "anchor")
  110.            (begin
  111.              (set! first (w 'index (format #f "~A wordstart" cur)))
  112.              (set! last  (w 'index "anchor - 1c wordend")))
  113.            (begin
  114.              (set! first (w 'index "anchor wordstart"))
  115.              (set! last  (w 'index (format #f "~A -1c wordend" cur))))))
  116.       ((string=? tk::select-mode "line")
  117.             (if (w 'compare cur "<" "anchor")
  118.             (begin
  119.               (set! first (w 'index (format #f "~A linestart" cur)))
  120.               (set! last  (w 'index "anchor - 1c lineend + 1c")))
  121.             (begin
  122.               (set! first (w 'index "anchor linestart"))
  123.               (set! last  (w 'index (format #f "~A lineend + 1c" cur)))))))
  124.      
  125.     (when (or tk::mouse-moved (not (equal? tk::select-mode "char")))
  126.     (w 'tag 'remove "sel" "0.0" first)
  127.     (w 'tag 'add "sel" first last)
  128.     (w 'tag 'remove "sel" last "end")
  129.     (update 'idletasks))))
  130.  
  131. ;; Tk:text-key-extend --
  132. ;; This procedure handles extending the selection from the keyboard,
  133. ;; where the point to extend to is really the boundary between two
  134. ;; characters rather than a particular character.
  135. ;;
  136. ;; w -        The text window.
  137. ;; index -    The point to which the selection is to be extended.
  138.  
  139. (define (Tk:text-key-extend w index)
  140.   (let ((cur    (w 'index index))
  141.     (anchor #f))
  142.     
  143.     (if (catch (w 'index 'anchor))
  144.     (w 'mark 'set 'anchor cur))
  145.     (set! anchor (w 'index 'anchor))
  146.  
  147.     (let ((first #f)
  148.       (last #f))
  149.       (if (w 'compare cur "<" anchor)
  150.       (begin
  151.         (set! first cur)
  152.         (set! last anchor))
  153.       (begin
  154.         (set! first anchor)
  155.         (set! last cur)))
  156.       
  157.       (w 'tag 'remove "sel" "0.0" first)
  158.       (w 'tag 'add "sel" first last)
  159.       (w 'tag 'remove "sel" last "end"))))
  160.  
  161.  
  162. ;; Tk:text-auto-scan --
  163. ;; This procedure is invoked when the mouse leaves an "Text" window
  164. ;; with button 1 down.  It scrolls the window left or right,
  165. ;; depending on where the mouse is, and reschedules itself as an
  166. ;; "after" command so that the window continues to scroll until the
  167. ;; mouse moves back into the window or the mouse button is released.
  168. ;;
  169. ;; w -    The "Text" window.
  170.  
  171. (define (Tk:text-auto-scan w)
  172.   (when (winfo 'exists w)
  173.     (let* ((x    tk::x)
  174.        (y    tk::y)
  175.        (cont (lambda () 
  176.            (Tk:text-select-to w x y)
  177.            (set! tk::after-id (after 50 (lambda () 
  178.                           (Tk:text-auto-scan w)))))))
  179.       (cond 
  180.        ((>= y (winfo 'height w))    (w 'yview 'scroll +2 'units) (cont))
  181.        ((< y 0)                (w 'yview 'scroll -2 'units) (cont))
  182.        ((>= x (winfo 'width w))        (w 'xview 'scroll +2 'units) (cont))
  183.        ((< x 0)                (w 'xview 'scroll -2 'units) (cont))))))
  184.  
  185.  
  186. ;; Tk:text-set-cursor
  187. ;; Move the insertion cursor to a given position in a text.  Also
  188. ;; clears the selection, if there is one in the text, and makes sure
  189. ;; that the insertion cursor is visible.  Also, don't let the insertion
  190. ;; cursor appear on the dummy last line of the text.
  191. ;;
  192. ;; w -        The text window.
  193. ;; pos -        The desired new position for the cursor in the window.
  194.  
  195. (define (Tk:text-set-cursor w pos)
  196.   (if (w 'compare pos "==" "end")
  197.       (set! pos "end - 1 chars"))
  198.  
  199.   (w 'mark 'set 'insert pos)
  200.   (w 'tag 'remove 'sel "1.0" "end")
  201.   (w 'see "insert"))
  202.  
  203.  
  204. ;; Tk:text-key-select --
  205. ;; This procedure is invoked when stroking out selections using the
  206. ;; keyboard.  It moves the cursor to a new position, then extends
  207. ;; the selection to that position.
  208. ;;
  209. ;; Arguments:
  210. ;; w -        The "Text" window.
  211. ;; new -    A new position for the insertion cursor (the cursor hasn't
  212. ;;        actually been moved to this position yet).
  213.  
  214. (define (Tk:text-key-select w new)
  215.   (if (equal? (w 'tag 'nextrange "sel" "1.0" "end") "")
  216.       (begin
  217.     (if (w 'compare new "<" "insert")
  218.         (w 'tag 'add "sel" new "insert")
  219.         (w 'tag 'add "sel" "insert" new))
  220.     (w 'mark 'set 'anchor "insert"))
  221.       (let ((first #f)
  222.         (last  #f))
  223.     (if (w 'compare new "<" 'anchor)
  224.         (begin
  225.           (set! first new)
  226.           (set! last "anchor"))
  227.         (begin
  228.           (set! first "anchor")
  229.           (set! last new)))
  230.     (w 'tag 'remove "sel" "1.0" first)
  231.     (w 'tag 'add "sel" first last)
  232.     (w 'tag 'remove "sel" last "end")))
  233.  
  234.   (w 'mark 'set "insert" new)
  235.   (w 'see "insert")
  236.   (update 'idletasks))
  237.  
  238.  
  239. ;; Tk:text-reset-anchor --
  240. ;; Set the selection anchor to whichever end is farthest from the
  241. ;; index argument.  One special trick: if the selection has two or
  242. ;; fewer characters, just leave the anchor where it is.  In this
  243. ;; case it doesn't matter which point gets chosen for the anchor,
  244. ;; and for the things like Shift-Left and Shift-Right this produces
  245. ;; better behavior when the cursor moves back and forth across the
  246. ;; anchor.
  247. ;;
  248. ;; w -        The text widget.
  249. ;; index -    Position at which mouse button was pressed, which determines
  250. ;;        which end of selection should be used as anchor point.
  251.  
  252. (define (Tk:text-reset-anchor w index)
  253.   (if (null? (w 'tag 'ranges "sel"))
  254.       (w 'mark 'set 'anchor index)
  255.       (let ((a     (w 'index index))
  256.         (b     (w 'index 'sel.first))
  257.         (c     (w 'index 'sel.last)))
  258.  
  259.     (if (w 'compare a "<" b)
  260.         (w 'mark 'set 'anchor 'sel.first)
  261.         (if (w 'compare a ">" c)
  262.         (w 'mark 'set 'anchor 'sel.first)
  263.         (if (< (car b) (+ (car c) 2))
  264.             (let ((total (string-length (w 'get b c))))
  265.               (when (> total 2)
  266.                 (w 'mark 
  267.                    'set 
  268.                    'anchor 
  269.                    (if (< (string-length (w 'get b c)) (/ total 2))
  270.                    'sel.last
  271.                    'sel.first))))
  272.             (w 'mark 
  273.                'set 
  274.                'anchor
  275.                (if (< (- (car a) (car b))
  276.                   (- (car c) (car a)))
  277.                'sel.last
  278.                'sel.first))))))))
  279.  
  280. ;; Tk:text-insert --
  281. ;; Insert a string into an "Text" at the point of the insertion cursor.
  282. ;; If there is a selection in the "Text", and it covers the point of the
  283. ;; insertion cursor, then delete the selection before inserting.
  284. ;;
  285. ;; w -        The "Text" window in which to insert the string
  286. ;; s -        The string to insert (usually just a single character)
  287.  
  288. (define (Tk:text-insert w s)
  289.   (unless (or (equal? s "") (equal? (tk-get w :state) "disabled"))
  290.      (catch
  291.         (if (and (w 'compare 'sel.first "<=" "insert")
  292.          (w 'compare 'sel.last ">="  "insert"))
  293.         (w 'delete 'sel.first 'sel.last)))
  294.      (w 'insert "insert" s)
  295.      (w 'see "insert")))
  296.  
  297. ;; Tk:text-up-down-line --
  298. ;; Returns the index of the character one line above or below the
  299. ;; insertion cursor.  There are two tricky things here.  First,
  300. ;; we want to maintain the original column across repeated operations,
  301. ;; even though some lines that will get passed through don't have
  302. ;; enough characters to cover the original column.  Second, don't
  303. ;; try to scroll past the beginning or end of the text.
  304. ;;
  305. ;; w -        The text window in which the cursor is to move.
  306. ;; n -        The number of lines to move: -1 for up one line,
  307. ;;        +1 for down one line.
  308.  
  309. (define Tk:text-up-down-line 
  310.   (let ((column 0)
  311.     (prev-pos (cons -1 -1)))
  312.     (lambda (w n)
  313.       (let ((p (w 'index "insert")))
  314.     
  315.     (unless (equal? prev-pos p)
  316.         (set! column (cdr p)))
  317.  
  318.     (let ((new (w 'index (cons (+ (car p) n) column))))
  319.       (if (or (w 'compare new "==" "end")
  320.           (w 'compare new "==" "insert linestart"))
  321.           (set! new p))
  322.       
  323.       (set! prev-pos new)
  324.       new)))))
  325.  
  326. ;; Tk:text-scroll-pages --
  327. ;; This is a utility procedure used in bindings for moving up and down
  328. ;; pages and possibly extending the selection along the way.  It scrolls
  329. ;; the view in the widget by the number of pages, and it returns the
  330. ;; index of the character that is at the same position in the new view
  331. ;; as the insertion cursor used to be in the old view.
  332. ;;
  333. ;; w -        The text window in which the cursor is to move.
  334. ;; count -    Number of pages forward to scroll;  may be negative
  335. ;;        to scroll backwards.
  336.  
  337. (define (Tk:text-scroll-pages w count)
  338.   (let ((bbox (w 'bbox "insert")))
  339.     (w 'yview 'scroll count 'pages)
  340.     (w 'index (if (null? bbox)
  341.           (format #f "@~A,~A" (truncate (/ (winfo 'height w) 2)) 0)
  342.           (format #f "@~A,~A" (car bbox) (cadr bbox))))))
  343.  
  344.  
  345. ;; Tk:text-transpose --
  346. ;; This procedure implements the "transpose" function for text widgets.
  347. ;; It tranposes the characters on either side of the insertion cursor,
  348. ;; unless the cursor is at the end of the line.  In this case it
  349. ;; transposes the two characters to the left of the cursor.  In either
  350. ;; case, the cursor ends up to the right of the transposed characters.
  351. ;;
  352. ;; Arguments:
  353. ;; w -        Text window in which to transpose.
  354.  
  355. (define (Tk:text-transpose w)
  356.   (let* ((pos (if (w 'compare "insert" "!=" "insert lineend")
  357.           "insert + 1 char"
  358.           "insert"))
  359.      (new (string-append (w 'get (format #f "~A - 1 char" pos))
  360.                  (w 'get (format #f "~A - 2 char" pos)))))
  361.  
  362.     (when (w 'compare (format #f "~A - 1 char" pos) "!=" "1.0")
  363.        (w 'delete (format #f "~A - 2 char" pos) pos)
  364.        (w 'insert "insert" new)
  365.        (w 'see "insert"))))
  366.  
  367.  
  368. ;; Tk:text-closest-gap --
  369. ;; Given x and y coordinates, this procedure finds the closest boundary
  370. ;; between characters to the given coordinates and returns the index
  371. ;; of the character just after the boundary.
  372. ;;
  373. ;; w -        The text window.
  374. ;; x -        X-coordinate within the window.
  375. ;; y -        Y-coordinate within the window.
  376.  
  377. (define (Tk:text-closest-gap w x y)
  378.   (let* ((pos  (w 'index (format #f "@~A,~A" x y)))
  379.      (bbox (w 'bbox  pos)))
  380.     (if (null? bbox)
  381.     (if (< [list-ref bbox 0] (/ [list-ref bbox 2] 2))
  382.         pos
  383.         (w 'index (format #f "~A + 1 char" pos)))
  384.     pos)))
  385.  
  386. ;; Tk:text-paste --
  387. ;; This procedure sets the insertion cursor to the mouse position,
  388. ;; inserts the selection, and sets the focus to the window.
  389. ;;
  390. ;; w -        The text window.
  391. ;; x, y -     Position of the mouse.
  392.  
  393. (define (Tk:text-paste |W| x y)
  394.   (|W| 'mark 'set 'insert (Tk:text-closest-gap |W| x y))
  395.   (catch (|W| 'insert 'insert (selection 'get :displayof |W|)))
  396.   (if (string=? (tk-get |W| :state) "normal")
  397.       (focus |W|)))
  398.  
  399. ;;-------------------------------------------------------------------------
  400. ;; The code below creates the default class bindings for entries.
  401. ;;-------------------------------------------------------------------------
  402.  
  403. ;; Standard Motif bindings:
  404.  
  405. (define-binding "Text" "<1>" (|W| x y)
  406.   (Tk:text-button-1 |W| x y)
  407.   (|W| 'tag 'remove "sel" "0.0" "end"))
  408.  
  409. (define-binding "Text" "<B1-Motion>" (|W| x y)
  410.   (set! tk::x x)
  411.   (set! tk::y y)
  412.   (Tk:text-select-to |W| x y))
  413.  
  414. (define-binding "Text" "<Double-1>" (|W| x y)
  415.   (set! tk::select-mode "word")
  416.   (Tk:text-select-to |W| x y)
  417.   (catch 
  418.      (|W| 'mark 'set "insert" 'sel.first)))
  419.  
  420. (define-binding "Text" "<Triple-1>" (|W| x y)
  421.   (set! tk::select-mode "line")
  422.   (Tk:text-select-to |W| x y)
  423.   (catch 
  424.       (|W| 'mark 'set "insert" 'sel.first)))
  425.  
  426. (define-binding "Text" "<Shift-1>" (|W| x y)
  427.   (Tk:text-reset-anchor |W| (format #f "@~A,~A" x y))
  428.   (set! tk::select-mode "char")
  429.   (Tk:text-select-to |W| x y))
  430.  
  431. (define-binding "Text" "<Double-Shift-1>" (|W| x y)
  432.   (set! tk::select-mode "word")
  433.   (Tk:text-select-to |W| x y))
  434.  
  435. (define-binding "Text" "<Triple-Shift-1>" (|W| x y)
  436.   (set! tk::select-mode "line")
  437.   (Tk:text-select-to |W| x y))
  438.  
  439. (define-binding "Text" "<B1-Leave>" (|W| x y)
  440.   (set! tk::x x)
  441.   (set! tk::y y)
  442.   (Tk:text-auto-scan |W|))
  443.  
  444. (define-binding "Text" "<B1-Enter>" ()
  445.   (Tk:cancel-repeat))
  446.  
  447. (define-binding "Text" "<ButtonRelease-1>" ()
  448.   (Tk:cancel-repeat))
  449.  
  450. (define-binding "Text" "<Control-1>" (|W| x y)
  451.   (|W| 'mark 'set "insert" (format #f "@~A,~A" x y)))
  452.  
  453. (define-binding "Text" "<ButtonRelease-2>" (|W| x y)
  454.   (if (or (not tk::mouse-moved) *tk-strict-motf*)
  455.       (Tk:text-paste |W| x y)))
  456.  
  457. (define-binding "Text" "<Left>" (|W|)
  458.   (Tk:text-set-cursor |W| "insert-1c"))
  459.  
  460. (define-binding "Text" "<Right>" (|W|)
  461.   (Tk:text-set-cursor |W| "insert+1c"))
  462.  
  463. (define-binding "Text" "<Up>" (|W|)
  464.   (Tk:text-set-cursor |W| (Tk:text-up-down-line |W| -1)))
  465.  
  466. (define-binding "Text" "<Down>" (|W|)
  467.   (Tk:text-set-cursor |W| (Tk:text-up-down-line |W| +1)))
  468.  
  469. (define-binding "Text" "<Shift-Left>" (|W|)
  470.   (Tk:text-key-select |W| (|W| 'index "insert-1c")))
  471.  
  472. (define-binding "Text" "<Shift-Right>" (|W|)
  473.   (Tk:text-key-select |W| (|W| 'index "insert+1c")))
  474.  
  475. (define-binding "Text" "<Shift-Up>" (|W|)
  476.   (Tk:text-key-select |W| (Tk:text-up-down-line |W| -1)))
  477.  
  478. (define-binding "Text" "<Shift-Down>" (|W|)
  479.   (Tk:text-key-select |W| (Tk:text-up-down-line |W| +1)))
  480.  
  481. (define-binding "Text" "<Control-Left>" (|W|)
  482.   (Tk:text-set-cursor |W| (|W| 'index "insert-1c wordstart")))
  483.  
  484. (define-binding "Text" "<Control-Right>" (|W|)
  485.   (Tk:text-set-cursor |W| (|W| 'index "insert wordend")))
  486.  
  487. (define-binding "Text" "<Shift-Control-Left>" (|W|)
  488.   (Tk:text-key-select |W|  (|W| 'index "insert-1c  wordstart")))
  489.  
  490. (define-binding "Text" "<Shift-Control-Right>" (|W|)
  491.   (Tk:text-key-select |W| (|W| 'index "insert wordend")))
  492.  
  493. (define-binding "Text" "<Prior>" (|W|)
  494.   (Tk:text-set-cursor |W| (Tk:text-scroll-pages |W| -1)))
  495.  
  496. (define-binding "Text" "<Shift-Prior>" (|W|)
  497.   (Tk:text-key-select |W| (Tk:text-scroll-pages |W| -1)))
  498.  
  499. (define-binding "Text" "<Next>" (|W|)
  500.   (Tk:text-set-cursor |W| (Tk:text-scroll-pages |W| +1)))
  501.  
  502. (define-binding "Text" "<Shift-Next>" (|W|)
  503.   (Tk:text-key-select |W| (Tk:text-scroll-pages |W| +1)))
  504.  
  505. (define-binding "Text" "<Control-Prior>" (|W|)
  506.   (|W| 'xview 'scroll -1 'page))
  507.  
  508. (define-binding "Text" "<Control-Next>" (|W|)
  509.   (|W| 'xview 'scroll 1 'page))
  510.  
  511. (define-binding "Text" "<Home>" (|W|)
  512.   (Tk:text-set-cursor |W| "insert linestart"))
  513.  
  514. (define-binding "Text" "<Shift-Home>" (|W|)
  515.   (Tk:text-set-cursor |W| "insert linestart"))
  516.  
  517. (define-binding "Text" "<End>" (|W|)
  518.   (Tk:text-set-cursor |W| "insert lineend"))
  519.  
  520. (define-binding "Text" "<Shift-End>" (|W|)
  521.   (Tk:text-set-cursor |W| "insert lineend"))
  522.  
  523. (define-binding "Text" "<Control-Home>" (|W|)
  524.   (Tk:text-set-cursor |W| "1.0"))
  525.  
  526. (define-binding "Text" "<Control-Shift-Home>" (|W|)
  527.   (Tk:text-key-select |W| "1.0"))
  528.  
  529. (define-binding "Text" "<Control-End>" (|W|)
  530.   (Tk:text-set-cursor |W| "end - 1 char"))
  531.  
  532. (define-binding "Text" "<Control-Shift-End>" (|W|)
  533.   (Tk:text-key-select |W| "end - 1 char"))
  534.  
  535. (define-binding "Text" "<Tab>" (|W|)
  536.   (Tk:text-insert |W| "\t")
  537.   (focus |W|)
  538.   'break)
  539.  
  540. (define-binding "Text" "<Shift-Tab>" (|W|)
  541.   ;; Needed only to keep <Tab> binding from triggering;  doesn't
  542.   ;; have to actually do anything.
  543.   'nop)
  544.  
  545. (define-binding "Text" "<Control-Tab>" (|W|)
  546.   (focus (Tk:focus-next |W|)))
  547.  
  548. (define-binding "Text" "<Control-Shift-Tab>" (|W|)
  549.   (focus (Tk:focus-prev |W|)))
  550.  
  551. (define-binding "Text" "<Control-i>" (|W|)
  552.   (Tk:text-insert |W| "\t"))
  553.  
  554. (define-binding "Text" "<Return>" (|W|)
  555.   (Tk:text-insert |W| "\n"))
  556.  
  557. (define-binding "Text" "<Delete>" (|W|)
  558.   (if (null? (|W| 'tag 'nextrange 'sel "1.0" "end"))
  559.       (begin 
  560.      (|W| 'delete "insert")
  561.      (|W| 'see "insert"))
  562.       (|W| 'delete 'sel.first 'sel.last)))
  563.  
  564. (define-binding "Text" "<BackSpace>" (|W|)
  565.   (if (null? (|W| 'tag 'nextrange 'sel "1.0" "end"))
  566.       (begin 
  567.      (|W| 'delete "insert-1c")
  568.      (|W| 'see "insert"))
  569.       (|W| 'delete 'sel.first 'sel.last)))
  570.  
  571. (define-binding "Text" "<Control-space>" (|W|)
  572.   (|W| 'mark 'set 'anchor "insert"))
  573.  
  574. (define-binding "Text" "<Select>" (|W|)
  575.  (|W| 'mark 'set 'anchor "insert"))
  576.  
  577. (define-binding "Text" "<Control-Shift-space>" (|W|)
  578.   (set! tk::select-mode "char")
  579.   (Tk:text-key-extend |W| "insert"))
  580.  
  581. (define-binding "Text" "<Shift-Select>" (|W|)
  582.   (set! tk::select-mode "char")
  583.   (Tk:text-key-extend |W| "insert"))
  584.  
  585. (define-binding "Text" "<Control-slash>" (|W|)
  586.   (|W| 'tag 'add 'sel "1.0" "end"))
  587.  
  588. (define-binding "Text" "<Control-backslash>" (|W|)
  589.   (|W| 'tag 'remove 'sel "1.0" "end"))
  590.  
  591. (Tk:text-clipboard-keysyms "<F16>" "<F20>" "<F18>")
  592.  
  593. (define-binding "Text" "<Insert>" (|W|)
  594.   (catch 
  595.      (Tk:text-insert |W| (selection 'get :displayof |W|))))
  596.  
  597. (define-binding "Text" "<KeyPress>" (|W| |A|)
  598.   (Tk:text-Insert |W| |A|))
  599.  
  600.  
  601. ;; Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
  602. ;; Otherwise, if a widget binding for one of these is defined, the
  603. ;; <KeyPress> class binding will also fire and insert the character,
  604. ;; which is wrong.  Ditto for Escape.
  605. (let ((nop (lambda () '())))
  606.   (bind "Text" "<Alt-KeyPress>"     nop)
  607.   (bind "Text" "<Meta-KeyPress>"     nop)
  608.   (bind "Text" "<Control-KeyPress>"     nop)
  609.   (bind "Text" "<Escape>"         nop)
  610.   (bind "Text" "<KP_Enter>"         nop))
  611.  
  612. ;; Additional emacs-like bindings:
  613.  
  614. (define-binding "Text" "<Control-a>" (|W|)
  615.   (Tk:text-set-cursor |W| "insert linestart"))
  616.  
  617. (define-binding "Text" "<Control-b>" (|W|)
  618.   (Tk:text-set-cursor |W| "insert-1c"))
  619.  
  620. (define-binding "Text" "<Control-d>" (|W|)
  621.   (|W| 'delete "insert"))
  622.  
  623. (define-binding "Text" "<Control-e>" (|W|)
  624.   (Tk:text-set-cursor |W| "insert lineend"))
  625.  
  626. (define-binding "Text" "<Control-f>" (|W|)
  627.   (Tk:text-set-cursor |W| "insert+1c"))
  628.  
  629. (define-binding "Text" "<Control-k>" (|W|)
  630.   (|W| 'delete "insert" (if (|W| 'compare "insert" "==" "insert lineend")
  631.                "insert+1c"
  632.                "insert lineend")))
  633.  
  634. (define-binding "Text" "<Control-n>" (|W|)
  635.   (Tk:text-set-cursor |W| (Tk:text-up-down-line |W| +1)))
  636.  
  637. (define-binding "Text" "<Control-o>" (|W|)
  638.   (|W| 'insert "insert" "\n")
  639.   (|W| 'mark 'set "insert" "insert-1c"))
  640.  
  641. (define-binding "Text" "<Control-p>" (|W|)
  642.   (Tk:text-set-cursor |W| (Tk:text-up-down-line |W| -1)))
  643.  
  644. (define-binding "Text" "<Control-t>" (|W|)
  645.   (Tk:text-transpose |W|))
  646.  
  647. (define-binding "Text" "<Control-v>" (|W|)
  648.   (Tk:text-scroll-pages |W| +1))
  649.  
  650. (define-binding "Text" "<Meta-b>" (|W|)
  651.   (Tk:text-set-cursor |W| "insert - 1c wordstart"))
  652.  
  653. (define-binding "Text" "<Meta-d>" (|W|)
  654.   (|W| 'delete "insert" "insert wordend"))
  655.  
  656. (define-binding "Text" "<Meta-f>" (|W|)
  657.   (Tk:text-set-cursor |W| "insert wordend"))
  658.  
  659. (define-binding "Text" "<Meta-less>" (|W|)
  660.   (Tk:text-set-cursor |W| "1.0"))
  661.  
  662. (define-binding "Text" "<Meta-greater>" (|W|)
  663.   (Tk:text-set-cursor |W| "end-1c"))
  664.  
  665. (define-binding "Text" "<Meta-BackSpace>" (|W|)
  666.   (|W| 'delete "insert -1c wordstart" "insert"))
  667.  
  668. (define-binding "Text" "<Meta-Delete>" (|W|)
  669.   (|W| 'delete "insert -1c wordstart" "insert"))
  670.  
  671. (Tk:text-clipboard-keysyms "<Meta-w>" "<Control-w>" "<Control-y>")
  672.  
  673. ;; A few additional bindings of my own.
  674.  
  675. (define-binding "Text" "<Control-h>" (|W|)
  676.   (when (|W| 'compare "insert" "!=" "1.0")
  677.     (|W| 'delete "insert-1c")
  678.     (|W| 'see "insert")))
  679.  
  680. (define-binding "Text" "<Shift-2>" (|W| x y)
  681.   (|W| 'scan 'mark x y)
  682.   (set! tk::x x)
  683.   (set! tk::y y)
  684.   (set! tk::mouse-moved #f))
  685.  
  686. (define-binding "Text" "<Shift-B2-Motion>" (|W| x y)
  687.   (unless (and  (= x tk::x) (= y tk::y))
  688.     (set! tk::mouse-moved #t))
  689.   (if tk::mouse-moved
  690.       (|W| 'scan 'dragto x y)))
  691.